package cn.b.sky.admin.security;

import cn.b.sky.admin.security.context.ManagementContext;
import cn.b.sky.admin.utils.AjaxUtil;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Set;

@WebFilter(urlPatterns = "/manage/management/*", filterName="managementFilter")
public class ManagementFilter implements Filter {

  private static final Logger LOGGER = LoggerFactory.getLogger(ManagementFilter.class);
  
  private final String loginFormUrl = "/manage/management/login";

  private final Set<String> ignoreUrl = new HashSet<String>();

  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    //初始化忽略的url，不拦截登陆url
    ignoreUrl.add(loginFormUrl);
    ignoreUrl.add("/manage/management/doLogin");
  }

  @Override
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;
    //每次进行context设置，通过session，session的属性不失效
    HttpSession session = request.getSession(true);
    if(session!=null && request.isRequestedSessionIdValid()){
      ManagementContext context = (ManagementContext) session.getAttribute(ManagementContextHolder.MANAGEMENT_SECURITY_CONTEXT);
      //设置ManagementContext
      if(context != null 
          && context.getAuthentication() != null){
        ManagementContextHolder.setContext(context);
        if(!requiresAuthentication(request, response)){
          String redirectUrl = request.getContextPath()+"/manage/management/index";
         // redirectUrl = response.encodeRedirectURL(redirectUrl);
          response.sendRedirect(redirectUrl);
          return;
        }
        chain.doFilter(request, response);
        return;
      }else{
        //不过滤登陆的url
        if(!requiresAuthentication(request, response)){
          chain.doFilter(request, response);
          return;
        }
      }
    }
    //未登录
    invidSessionChain(request, response);
  }

  private void invidSessionChain(HttpServletRequest request, HttpServletResponse response) throws IOException,
          ServletException {

    String url = request.getRequestURI();

    if (LOGGER.isDebugEnabled()) {
      LOGGER.debug("url:" + url);
    }
    // 非ajax请求
    boolean isAjax = AjaxUtil.isAjax(request);
    if (!isAjax) {
      RequestDispatcher dispatcher = request.getRequestDispatcher(loginFormUrl);
      dispatcher.forward(request, response);
      /*String redirectUrl = request.getContextPath()+loginFormUrl;
      response.sendRedirect(redirectUrl);*/
    } else {
      // ajax请求，返回json，替代redirect到login page
      if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("ajax request or post");
      }

      response.setHeader("Content-Type", "application/json;charset=UTF-8");
      response.setContentType("application/json;charset=UTF-8");
      /**
       * 调用dwz的超时返回状态
       * 
       * @author lidapeng
       */
      String jsonObject = JSONObject.toJSONString(AjaxUtil.ajaxTimeout(null));
      PrintWriter out = response.getWriter();
      out.print(jsonObject);
      out.flush();
      out.close();
    }
  }

  protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
    String uri = request.getRequestURI();
    int pathParamIndex = uri.indexOf(';');

    if (pathParamIndex > 0) {
      // strip everything after the first semi-colon
      uri = uri.substring(0, pathParamIndex);
    }
    //不需要过滤的地方
    for (String ignore : ignoreUrl) {
      if ("".equals(request.getContextPath())) {
        if (uri.endsWith(ignore)) {
          return false;
        }
      } else if (uri.endsWith(request.getContextPath() + ignore)) {
        return false;
      }
    }
    return true;
  }

  @Override
  public void destroy() {

  }

}
